#include "../src/executor/executor.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>

// Test helper functions
static void print_test_header(const char* test_name);
static void print_test_result(const char* test_name, bool passed);

static void print_test_header(const char* test_name) {
    printf("\n=== %s ===\n", test_name);
}

static void print_test_result(const char* test_name, bool passed) {
    printf("%s: %s\n", test_name, passed ? "PASSED" : "FAILED");
}

// Test executor context creation and destruction (without memory manager)
static bool test_executor_context_simple(void) {
    print_test_header("Testing Executor Context Management (Simple)");
    
    executor_context_t* context = executor_create_context(NULL, NULL, NULL);
    if (!context) {
        printf("Failed to create executor context\n");
        return false;
    }
    
    printf("Created executor context successfully\n");
    printf("  Work memory: %u KB\n", context->work_mem_kb);
    printf("  Hash join enabled: %s\n", context->enable_hashjoin ? "true" : "false");
    printf("  Merge join enabled: %s\n", context->enable_mergejoin ? "true" : "false");
    printf("  Nested loop enabled: %s\n", context->enable_nestloop ? "true" : "false");
    
    executor_destroy_context(context);
    printf("Destroyed executor context successfully\n");
    
    return true;
}

// Test tuple and value management
static bool test_tuple_management(void) {
    print_test_header("Testing Tuple Management");
    
    bool all_passed = true;
    
    // Test tuple creation
    tuple_t* tuple = tuple_create(3);
    if (!tuple) {
        printf("Failed to create tuple\n");
        return false;
    }
    
    printf("Created tuple with %u columns\n", tuple->slot->column_count);
    
    // Test value creation and assignment
    tuple->slot->values[0] = value_make_int32(42);
    tuple->slot->values[1] = value_make_string("hello");
    tuple->slot->values[2] = value_make_bool(true);
    
    tuple->slot->is_null[0] = false;
    tuple->slot->is_null[1] = false;
    tuple->slot->is_null[2] = false;
    
    printf("Assigned values to tuple:\n");
    printf("  Column 0: %d (type: %s)\n", 
           tuple->slot->values[0].data.int32_val,
           value_type_to_string(tuple->slot->values[0].type));
    printf("  Column 1: %s (type: %s)\n", 
           tuple->slot->values[1].data.string_val.data,
           value_type_to_string(tuple->slot->values[1].type));
    printf("  Column 2: %s (type: %s)\n", 
           tuple->slot->values[2].data.bool_val ? "true" : "false",
           value_type_to_string(tuple->slot->values[2].type));
    
    // Test tuple copy
    tuple_t* copy = tuple_copy(tuple);
    if (!copy) {
        printf("Failed to copy tuple\n");
        all_passed = false;
    } else {
        printf("Successfully copied tuple\n");
        
        // Verify copy is independent
        bool values_match = 
            value_equals(&tuple->slot->values[0], &copy->slot->values[0]) &&
            value_equals(&tuple->slot->values[1], &copy->slot->values[1]) &&
            value_equals(&tuple->slot->values[2], &copy->slot->values[2]);
        
        if (values_match) {
            printf("Copied tuple values match original\n");
        } else {
            printf("Copied tuple values don't match original\n");
            all_passed = false;
        }
        
        tuple_destroy(copy);
    }
    
    tuple_destroy(tuple);
    printf("Destroyed tuples successfully\n");
    
    return all_passed;
}

// Test value operations
static bool test_value_operations(void) {
    print_test_header("Testing Value Operations");
    
    bool all_passed = true;
    
    // Test value creation
    value_t v1 = value_make_int32(10);
    value_t v2 = value_make_int32(20);
    value_t v3 = value_make_int32(10);
    value_t v_null = value_make_null();
    
    // Test equality
    if (value_equals(&v1, &v3)) {
        printf("Value equality test passed (10 == 10)\n");
    } else {
        printf("Value equality test failed (10 == 10)\n");
        all_passed = false;
    }
    
    if (!value_equals(&v1, &v2)) {
        printf("Value inequality test passed (10 != 20)\n");
    } else {
        printf("Value inequality test failed (10 != 20)\n");
        all_passed = false;
    }
    
    if (!value_equals(&v1, &v_null)) {
        printf("Null comparison test passed (10 != NULL)\n");
    } else {
        printf("Null comparison test failed (10 != NULL)\n");
        all_passed = false;
    }
    
    // Test comparison
    int cmp = value_compare(&v1, &v2);
    if (cmp < 0) {
        printf("Value comparison test passed (10 < 20)\n");
    } else {
        printf("Value comparison test failed (10 < 20)\n");
        all_passed = false;
    }
    
    // Test string values
    value_t s1 = value_make_string("apple");
    value_t s2 = value_make_string("banana");
    value_t s3 = value_make_string("apple");
    
    if (value_equals(&s1, &s3)) {
        printf("String equality test passed\n");
    } else {
        printf("String equality test failed\n");
        all_passed = false;
    }
    
    if (value_compare(&s1, &s2) < 0) {
        printf("String comparison test passed (apple < banana)\n");
    } else {
        printf("String comparison test failed (apple < banana)\n");
        all_passed = false;
    }
    
    // Clean up
    value_destroy(&v1);
    value_destroy(&v2);
    value_destroy(&v3);
    value_destroy(&v_null);
    value_destroy(&s1);
    value_destroy(&s2);
    value_destroy(&s3);
    
    return all_passed;
}

// Test error handling
static bool test_error_handling(void) {
    print_test_header("Testing Error Handling");
    
    executor_context_t* context = executor_create_context(NULL, NULL, NULL);
    if (!context) {
        printf("Failed to create executor context\n");
        return false;
    }
    
    bool all_passed = true;
    
    // Test error setting and retrieval
    executor_set_error(context, -1, "Test error message");
    
    if (executor_has_error(context)) {
        printf("Error state correctly detected\n");
        printf("  Error message: %s\n", executor_get_error_message(context));
    } else {
        printf("Failed to detect error state\n");
        all_passed = false;
    }
    
    // Test NULL handling
    exec_result_t result = executor_open(NULL);
    if (result == EXEC_ERROR) {
        printf("NULL executor correctly handled\n");
    } else {
        printf("NULL executor not handled correctly\n");
        all_passed = false;
    }
    
    executor_destroy_context(context);
    
    return all_passed;
}

// Test executor result strings
static bool test_result_strings(void) {
    print_test_header("Testing Result Strings");
    
    printf("Testing exec_result_to_string:\n");
    printf("  EXEC_SUCCESS: %s\n", exec_result_to_string(EXEC_SUCCESS));
    printf("  EXEC_EOF: %s\n", exec_result_to_string(EXEC_EOF));
    printf("  EXEC_ERROR: %s\n", exec_result_to_string(EXEC_ERROR));
    printf("  EXEC_QUAL_FALSE: %s\n", exec_result_to_string(EXEC_QUAL_FALSE));
    printf("  EXEC_RESCAN: %s\n", exec_result_to_string(EXEC_RESCAN));
    
    printf("Testing value_type_to_string:\n");
    printf("  VALUE_NULL: %s\n", value_type_to_string(VALUE_NULL));
    printf("  VALUE_BOOL: %s\n", value_type_to_string(VALUE_BOOL));
    printf("  VALUE_INT32: %s\n", value_type_to_string(VALUE_INT32));
    printf("  VALUE_INT64: %s\n", value_type_to_string(VALUE_INT64));
    printf("  VALUE_STRING: %s\n", value_type_to_string(VALUE_STRING));
    
    return true;
}

// Test executor statistics
static bool test_executor_statistics(void) {
    print_test_header("Testing Executor Statistics");
    
    executor_context_t* context = executor_create_context(NULL, NULL, NULL);
    if (!context) {
        printf("Failed to create executor context\n");
        return false;
    }
    
    // Set some test statistics
    context->total_tuples_processed = 1000;
    context->total_pages_read = 50;
    context->total_pages_written = 10;
    context->execution_time_us = 5000;
    
    printf("Executor statistics:\n");
    executor_print_stats(context);
    
    executor_destroy_context(context);
    
    return true;
}

int main() {
    printf("Executor Test Suite (Simple)\n");
    printf("============================\n");
    
    int passed = 0;
    int total = 0;
    
    // Run all tests
    struct {
        const char* name;
        bool (*test_func)(void);
    } tests[] = {
        {"Executor Context Management (Simple)", test_executor_context_simple},
        {"Tuple Management", test_tuple_management},
        {"Value Operations", test_value_operations},
        {"Error Handling", test_error_handling},
        {"Result Strings", test_result_strings},
        {"Executor Statistics", test_executor_statistics},
        {NULL, NULL}
    };
    
    for (int i = 0; tests[i].name != NULL; i++) {
        total++;
        bool result = tests[i].test_func();
        if (result) {
            passed++;
        }
        print_test_result(tests[i].name, result);
    }
    
    printf("\n=== Test Summary ===\n");
    printf("Passed: %d/%d\n", passed, total);
    printf("Success rate: %.1f%%\n", (double)passed / total * 100.0);
    
    return (passed == total) ? 0 : 1;
}